package com.polaris.live.widget.refresh

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.CheckResult
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.chad.library.adapter.base.BaseQuickAdapter
import com.polaris.live.R
import com.polaris.live.common.adapter.AdapterLoadMoreView
import com.polaris.live.common.adapter.BaseAdapter
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.databinding.WidgetRefreshRecyclerviewBinding
import com.polaris.live.resp.base.ListResp
import com.polaris.live.widget.CustomNestedScrollView
import com.scwang.smart.refresh.footer.ClassicsFooter
import com.scwang.smart.refresh.header.FalsifyFooter
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.zhpan.bannerview.annotation.Visibility
import java.util.TreeSet

/**
 * RefreshRecyclerView
 *
 * @author Created by lucas on 2023/10/16 20:32
 */
class RefreshRecyclerView(context: Context, attrs: AttributeSet? = null) :
    SmartRefreshLayout(context, attrs) {

    private val mBinding =
        WidgetRefreshRecyclerviewBinding.inflate(LayoutInflater.from(context), this, true)

    val recycler = mBinding.recycler

    private var mAdapter: BaseQuickAdapter<*, *>? = null

    private var isLoading = true
    private var lastSuccess = true

    private val emptyView by lazy { EmptyView(context) }

    private val errorView by lazy { ErrorView(context) }

    private var isFristRefresh = true

    init {
        setEnableLoadMore(false)
        setEnableOverScrollBounce(false)
        setEnableOverScrollDrag(false)

        setHeaderTriggerRate(0.75f)
        setHeaderMaxDragRate(2f)

        setRefreshHeader(MlRefreshHeader(context), 1, 1)

        setRefreshFooter(ClassicsFooter(context).apply {
            setFinishDuration(0)
        })

        //默认去除动画，在大部分需要状态更新的情况下，这里显得很奇怪
        recycler.itemAnimator = null

        //滑动嵌套
        if (attrs != null) {
            val typedArray =
                getContext().obtainStyledAttributes(attrs, R.styleable.RefreshRecyclerView)

            val viewPagerNested =
                typedArray.getBoolean(R.styleable.RefreshRecyclerView_viewPagerNested, false)
            val viewPagerToScroll =
                typedArray.getBoolean(R.styleable.RefreshRecyclerView_viewPagerToScroll, false)
            mBinding.recycler.setViewPagerNested(viewPagerNested)
            setViewPagerToScroll(viewPagerToScroll)
            typedArray.recycle()
        }
    }

    /**
     * 设置空显示
     */
    fun setEmptyTip(@DrawableRes img: Int, tip: String, @ColorInt color: Int? = null) {
        emptyView.setEmptyTip(img, tip, color)
    }

    /**
     * 设置适配器
     */
    fun setAdapter(adapter: BaseQuickAdapter<*, *>) {
        adapter.setEmptyView(LoadingView(context))

        recycler.adapter = adapter
        mAdapter = adapter
        isLoading = true
    }

    /**
     * 附加适配器
     */
    @CheckResult
    fun <T> attachedAdapter(
        adapter: BaseQuickAdapter<T, *>,
        onListListener: OnListListener,
    ): ListOperator<T> {
        setAdapter(adapter)

        return ListOperator(this, adapter, onListListener)
    }

    override fun finishRefresh(success: Boolean): RefreshLayout {
        handleEmptyView(success)
        if (isFristRefresh) {
            setRefreshHeader(MlRefreshHeader(context))
            isFristRefresh = false
        }
        return super.finishRefresh(success)
    }

    override fun finishRefresh(
        delayed: Int,
        success: Boolean,
        noMoreData: Boolean?,
    ): RefreshLayout {
        handleEmptyView(success)
        if (isFristRefresh) {
            setRefreshHeader(MlRefreshHeader(context))
            isFristRefresh = false
        }
        return super.finishRefresh(delayed, success, noMoreData)
    }

    private fun handleEmptyView(success: Boolean) {
        if (isLoading || lastSuccess != success) {
            if (success) {
                mBinding.recycler.post {
                    emptyView.layoutParams = ViewGroup.LayoutParams(mBinding.recycler.width, mBinding.recycler.height)
                    mAdapter?.setEmptyView(emptyView)
                }
            } else {
                mBinding.recycler.post {
                    errorView.layoutParams = ViewGroup.LayoutParams(mBinding.recycler.width, mBinding.recycler.height)
                    mAdapter?.setEmptyView(errorView)
                }
            }
        }
        lastSuccess = success
        isLoading = false
    }

    fun setErrorTest(message: String?) {
        errorView.setText(message ?: "unknown")
    }

    fun showEmptyView(@Visibility showTip: Int) {
        mBinding.wdigetEmpty.visibility = showTip
    }

    //这个是当viewPager2嵌套viewPager2在使用recyclerView使用的，如果使用viewPagerNested会导致第二次viewPager2无法滑动
    //之所以不在外部套CustomNestedScrollView 是因为NestedScrollView嵌套SmartRefreshLayout有可能导致刷新头无法隐藏
    fun setViewPagerToScroll(viewPagerToScroll: Boolean) {
        if (viewPagerToScroll) {
            mBinding.recycler.post {
                // 创建 CustomNestedScrollView
                val nestedScrollView = CustomNestedScrollView(context)
                nestedScrollView.layoutParams = ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.MATCH_PARENT,
                    ConstraintLayout.LayoutParams.MATCH_PARENT
                )
                // 创建一个新的容器，用于包裹 XRecyclerView
                val container = FrameLayout(context)
                container.layoutParams = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT
                )
                // 检查 XRecyclerView 是否已经有父视图，如果有，先从父视图中移除
                if (mBinding.recycler.parent != null) {
                    (mBinding.recycler.parent as ViewGroup).removeView(mBinding.recycler)
                }

                // 将 XRecyclerView 添加到容器中
                container.addView(mBinding.recycler)

                // 将容器添加到 NestedScrollView 中
                nestedScrollView.addView(container)

                // 最后将 NestedScrollView 添加到 ConstraintLayout 中
                mBinding.constraintLayout.addView(nestedScrollView)
            }
        }
    }

}

class ListOperator<T> internal constructor(
    private val refreshView: RefreshRecyclerView,
    private val adapter: BaseQuickAdapter<T, *>,
    private val onListListener: OnListListener,
) {

    private var pageIndex = 0

    init {
        refreshView.setOnRefreshListener {
            pageIndex = 0
            onListListener.onRefresh()
        }
        if (adapter is BaseAdapter) {
            refreshView.setRefreshFooter(FalsifyFooter(refreshView.context))
            adapter.loadMoreModule.loadMoreView = adapterLoadMoreView
            adapter.loadMoreModule.preLoadNumber = 2
            adapter.loadMoreModule.setOnLoadMoreListener {
                onListListener.onLoadMore(++pageIndex)
            }
        } else {
            refreshView.setOnLoadMoreListener {
                onListListener.onLoadMore(++pageIndex)
            }
        }
    }

    /**
     * 绑定分页的
     */
    fun observeFilter(
        owner: LifecycleOwner,
        liveData: MutableLiveData<ResultState<ListResp<T>>>,
        comparator: Comparator<T>,
        onPostListener: (Int.(ResultState<ListResp<T>>) -> Unit)? = null,
    ) {
        liveData.observe(owner, object : Observer<ResultState<ListResp<T>>> {

            private val excludeSet = TreeSet(comparator)

            override fun onChanged(it: ResultState<ListResp<T>>) {

                when (it) {
                    is ResultState.Success -> {
                        if (pageIndex == 0) {
                            adapter.data.clear()
                            excludeSet.clear()

                            excludeSet.addAll(it.data.list)

                            adapter.setList(it.data.list)
                        } else {
                            val finalData = it.data.list.filter {
                                excludeSet.add(it)
                            }

                            adapter.addData(finalData)
                        }

                        if (pageIndex == 0) {
                            refreshView.finishRefresh()
                        } else {
                            finishLoadMore()
                        }
                        if (it.data.hasMore) {
                            setEnableLoadMore(true)
                        } else {
                            setEnableLoadMore(false)
                        }
                    }

                    is ResultState.Error -> {
                        if (pageIndex == 0) {
                            refreshView.finishRefresh(false)
                            setEnableLoadMore(false)
                        } else {
                            finishLoadMoreFail()
                        }

                        refreshView.setErrorTest(it.error.errorMsg)

                        if (adapter.data.isNotEmpty()) {
                            ToastGravity.showGravity(it.error.errorMsg)
                        }
                    }
                }

                onPostListener?.invoke(pageIndex, it)
            }
        })
    }

    /**
     * 重置数据
     */
    fun resetData() {
        pageIndex = 0
        adapter.data.clear()
    }

    /**
     * 绑定分页的
     */
    fun observe(
        owner: LifecycleOwner,
        liveData: MutableLiveData<ResultState<ListResp<T>>>,
        onPostListener: (Int.(ResultState<ListResp<T>>) -> Unit)? = null,
    ) {
        liveData.observe(owner) {
            when (it) {
                is ResultState.Success -> {
                    if (pageIndex == 0) {
                        adapter.setList(it.data.list)
                    } else {
                        adapter.addData(it.data.list)
                    }

                    if (pageIndex == 0) {
                        refreshView.finishRefresh()
                    } else {
                        finishLoadMore()
                    }
                    if (it.data.hasMore) {
                        setEnableLoadMore(true)
                    } else {
                        setEnableLoadMore(false)
                    }
                }

                is ResultState.Error -> {
                    if (pageIndex == 0) {
                        refreshView.finishRefresh(false)
                        setEnableLoadMore(false)
                    } else {
                        finishLoadMoreFail()
                    }

                    refreshView.setErrorTest(it.error.errorMsg)

                    if (adapter.data.isNotEmpty()) {
                        ToastGravity.showGravity(it.error.errorMsg)
                    }
                }
            }

            onPostListener?.invoke(pageIndex, it)
        }
    }

    /**
     * 绑定普通的list
     *
     * 如果一次获取的小于[pageSize]将停止加载更多
     */
    fun observeList(
        owner: LifecycleOwner,
        pageSize: Int,
        liveData: MutableLiveData<ResultState<List<T>>>,
        onPostListener: (Int.(ResultState<List<T>>) -> Unit)? = null,
    ) {
        liveData.observe(owner) {
            when (it) {
                is ResultState.Success -> {
                    if (pageIndex == 0) {
                        adapter.setList(it.data)
                    } else {
                        adapter.addData(it.data)
                    }

                    if (pageIndex == 0) {
                        refreshView.finishRefresh(0)
                    } else {
                        finishLoadMore()
                    }
                    if (it.data.size >= pageSize) {
                        setEnableLoadMore(true)
                    } else {
                        setEnableLoadMore(false)
                    }
                }

                is ResultState.Error -> {
                    if (pageIndex == 0) {
                        refreshView.finishRefresh(0, success = false, noMoreData = false)
                        setEnableLoadMore(false)
                    } else {
                        finishLoadMoreFail()
                    }

                    refreshView.setErrorTest(it.error.errorMsg)

                    if (adapter.data.isNotEmpty()) {
                        ToastGravity.showGravity(it.error.errorMsg)
                    }
                }
            }

            onPostListener?.invoke(pageIndex, it)
        }
    }

    private fun finishLoadMore() {
        if (adapter is BaseAdapter) {
            adapter.loadMoreModule.loadMoreComplete()
        } else {
            refreshView.finishLoadMore(0)
        }
    }

    private fun finishLoadMoreFail() {
        if (adapter is BaseAdapter) {
            adapter.loadMoreModule.loadMoreFail()
        } else {
            refreshView.finishLoadMore(0, false, false)
        }
    }

    private fun setEnableLoadMore(enabled: Boolean) {
        if (adapter is BaseAdapter) {
            adapter.loadMoreModule.isEnableLoadMore = enabled
        } else {
            refreshView.setEnableLoadMore(enabled)
        }
    }

    companion object {

        var adapterLoadMoreView = AdapterLoadMoreView()
    }
}
